View Javadoc
1 /************************************************************ 2 * Copyright * 3 * Portions of this software are Copyright (c) 1993 - 2002, * 4 * Chad Z. Hower (Kudzu) and the Indy Pit Crew * 5 * - http://www.nevrona.com/Indy/ * 6 ************************************************************/ 7 8 /************************************************************ 9 * Copyright * 10 * Portions of this software are Copyright (c) 1993 - 2002, * 11 * Chad Z. Hower (Kudzu) and the Indy Pit Crew * 12 * - http://www.nevrona.com/Indy/ * 13 ************************************************************/ 14 package org.indy.io; 15 16 import java.io.BufferedInputStream; 17 import java.io.BufferedOutputStream; 18 import java.io.ByteArrayOutputStream; 19 import java.io.IOException; 20 import java.io.InputStream; 21 import java.io.InterruptedIOException; 22 23 import java.net.InetAddress; 24 import java.net.Socket; 25 import java.net.SocketException; 26 import java.net.UnknownHostException; 27 28 import java.util.Map; 29 30 import org.indy.IndyException; 31 import org.indy.Status; 32 33 import org.indy.socks.SocksInfo; 34 35 import org.indy.util.IndyUtilities; 36 37 38 /*** 39 * An implementation of {@link IOHandler} that handles IO for sockets. 40 * 41 *@see IOHandler 42 *@see AbstractIOHandler 43 *@author Owen Green 44 */ 45 public class IOHandlerSocket extends AbstractIOHandler { 46 /*** 47 * Carriage Return 48 */ 49 protected static final int CR = 13; 50 51 /*** 52 * Line Feed 53 */ 54 protected static final int LF = 10; 55 private final ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); 56 private MutableBufferedInputStream input; 57 private BufferedOutputStream output; 58 private SocksInfo _info = null; 59 private boolean useNagle = true; 60 private boolean connected = false; 61 62 /*** 63 * Instance of <code>java.net.Socket</code> used by this IOHandler. 64 */ 65 protected Socket binding = null; 66 67 /*** 68 * Constructs a new instance of <code>IOHandlerSocket</code> 69 * around a pre-made <code>java.net.Socket</code> 70 * 71 * @param socket The socket to use with the IOHandler 72 * @throws IndyIOException If an IO error occurs whilst configuring the socket 73 */ 74 public IOHandlerSocket(Socket socket) throws IndyIOException { 75 if (socket == null) { 76 /*** @todo resource message */ 77 throw new NullPointerException("Socket is null"); 78 } 79 80 binding = socket; 81 82 try { 83 binding.setKeepAlive(false); 84 85 input = new MutableBufferedInputStream(binding.getInputStream()); 86 output = new BufferedOutputStream(binding.getOutputStream()); 87 } 88 catch (IOException ex) { 89 ex.printStackTrace(); 90 throw new IndyIOException(ex); 91 } 92 93 connected = true; 94 } 95 96 /*** 97 * Constructs a new instance of <code>IOHandlerSocket</code> 98 */ 99 public IOHandlerSocket() { 100 } 101 102 /*** 103 * Sets the SOCKS configuration to be used with this socket connection. 104 * NOTE: Setting this whilst the socket is connected will have no effect. 105 * 106 *@param info The new socks configuration data to be used. 107 */ 108 protected void setSocksInfo(SocksInfo info) { 109 _info = new SocksInfo(info); 110 } 111 112 /*** 113 * Sets whether to use Nagle's Algorithm with this socket or not. 114 * The default is <code>true</code> 115 * 116 *@param use <code>true</code> to use Nagle's Algorithm, <code>false</code> otherwise 117 *@throws IndyIOException if the underlying socket throws an exception whilst setting this property 118 *@see java.net.Socket#setTcpNoDelay(boolean) 119 */ 120 public void setUseNagle(boolean use) throws IndyIOException { 121 useNagle = use; 122 123 if (isConnected()) { 124 try { 125 binding.setTcpNoDelay(use); 126 } 127 catch (SocketException se) { 128 throw new IndyIOException(se); 129 } 130 } 131 } 132 133 /*** 134 * Gets the SOCKS data in use with this <code>IOHandlerSocket</code> 135 * 136 *@return The current SOCKS configuration 137 */ 138 protected SocksInfo getSocksInfo() { 139 return new SocksInfo(_info); 140 } 141 142 /*** 143 * Returns a string representing the IP address of the peer that 144 * this socket is connected to, or a blank string if the socket 145 * is not connected. 146 * 147 *@return The IP address of the socket's peer, or a blank string if unconnected. 148 */ 149 public String getPeerIP() { 150 if (connected) { 151 return binding.getInetAddress().getHostAddress(); 152 } 153 else { 154 return ""; 155 } 156 } 157 158 /*** 159 * Gets the remote port to which this socket is connected, or 0 if unconnected 160 * 161 *@return The remote port. 162 */ 163 public int getPeerPort() { 164 if (connected) { 165 return binding.getPort(); 166 } 167 else { 168 return 0; 169 } 170 } 171 172 /*** 173 * Gets a string representation of the local IP address that this 174 * socket is bound to, or throws an exception if the socket is not bound. 175 * 176 *@return The local IP address that this socket is bound to 177 *@throws IndyException If the socket is not bound 178 *@see connectClient 179 */ 180 public String getBoundIP() throws IndyException { 181 if (binding != null) { 182 return binding.getLocalAddress().getHostAddress(); 183 } 184 else { 185 throw new IndyException(IndyUtilities.getResourceString("RSNotBound")); 186 } 187 } 188 189 /*** 190 * Gets the local port number that this socket is bound to. 191 * 192 *@return The local port that this socket is bound to. 193 *@throws IndyException if the socket is not bound 194 *@see connectClient 195 */ 196 public int getBoundPort() throws IndyException { 197 if (binding != null) { 198 return binding.getLocalPort(); 199 } 200 else { 201 throw new IndyException(IndyUtilities.getResourceString("RSNotBound")); 202 } 203 } 204 205 /*** 206 * Returns whether this socket is using Nagle's Algortihm. 207 * 208 *@return <code>true</code> if the socket is using Nagle's Algorithm, <code>false</code> otherwise 209 */ 210 public boolean getUseNagle() throws IndyIOException { 211 if (isConnected()) { 212 try { 213 return binding.getTcpNoDelay(); 214 } 215 catch (SocketException ex) { 216 throw new IndyIOException(ex); 217 } 218 } 219 220 return useNagle; 221 } 222 223 /*** 224 * Returns whether or not this instance is connected. 225 * 226 *@return <code>true</code> if the socket is connected. 227 */ 228 public boolean isConnected() { 229 if (binding == null) { 230 connected = false; 231 } 232 233 /* if(connected){ 234 try { 235 input.mark(1); 236 int b = input.read(); 237 if(b==-1){ 238 close(); 239 } 240 else{ 241 input.reset(); 242 } 243 } 244 catch (IOException ex) { 245 close(); 246 } 247 }*/ 248 return connected; 249 } 250 251 /*** 252 * Flushes the output buffer of this <code>IOHandlerSocket</code> 253 * 254 *@throws IndyIOException If an IO error occurs whilst flushing 255 *@throws NotConnectedException if the socket is not connected 256 */ 257 public void flush() throws IndyIOException { 258 ensureOpen(); 259 260 try { 261 output.flush(); 262 } 263 catch (IOException ex) { 264 throw new IndyIOException(ex); 265 } 266 } 267 268 /*** 269 * Writes a seqeunce of bytes to the socket 270 * 271 *@param b An array of bytes containing the data 272 *@param off The offset at which to start writing 273 *@param len The number of bytes to write 274 *@throws IndyIOException If an IO error occurs 275 *@throws NotConnectedException if the socket is not connected 276 *@throws IndexOutOfBoundsException if there are illegal values of <code>b,off,or len</code> 277 */ 278 public void write(byte[] b, int off, int len) throws IndyIOException { 279 ensureOpen(); 280 281 try { 282 output.write(b, off, len); 283 } 284 catch (IOException ex) { 285 throw new IndyIOException(ex); 286 } 287 } 288 289 /*** 290 * Writes a sequence of bytes to the socket 291 * 292 *@param b The data to write 293 *@throws IndyIOException If an IO error occurs 294 *@see write(byte[],int,int) 295 */ 296 public void write(byte[] b) throws IndyIOException { 297 write(b, 0, b.length); 298 } 299 300 /*** 301 * Writes a single byte to the socket 302 * 303 *@param b The byte to write 304 *@throws IndyIOException If an IO error occurs 305 */ 306 public void write(int b) throws IndyIOException { 307 try { 308 output.write(b); 309 } 310 catch (IOException ex) { 311 throw new IndyIOException(ex); 312 } 313 } 314 315 /*** 316 * Reads a single byte of data from the socket 317 * 318 *@return The byte that was read 319 *@throws IndyIOException if an IO error occurs. 320 *@throws PeerDisconnectedException if the remote machine has disconnected 321 *@throws ReadTimedOutException if the read opertaion timed out 322 *@throws NotConnectedException if the socket is not connected 323 */ 324 public int read() throws IndyIOException, PeerDisconnectedException, 325 ReadTimedOutException { 326 ensureOpen(); 327 328 try { 329 int b = input.read(); 330 331 if (b == -1) { 332 close(); 333 throw new PeerDisconnectedException(IndyUtilities.getResourceString( 334 "RSConnectionClosedGracefully")); 335 } 336 337 return b; 338 } 339 catch (InterruptedIOException ex) { 340 throw new ReadTimedOutException(IndyUtilities.getResourceString( 341 "RSReadTimedOut")); 342 } 343 catch (IOException ex) { 344 close(); 345 throw new IndyIOException(ex); 346 } 347 } 348 349 /*** 350 * DOCUMENT ME! 351 * 352 * @param timeout DOCUMENT ME! 353 * 354 * @return DOCUMENT ME! 355 * 356 * @throws IndyIOException DOCUMENT ME! 357 */ 358 public int read(int timeout) throws IndyIOException { 359 ensureOpen(); 360 361 int oldTime = getReadTimeOut(); 362 363 setReadTimeOut(timeout); 364 365 try { 366 return read(); 367 } 368 finally { 369 setReadTimeOut(oldTime); 370 } 371 } 372 373 /*** 374 * Reads a sequence of bytes from the socket, using the 375 * specified timeout. 376 * 377 *@param b An array of bytes to read the data into 378 *@param off The offset at which to start writing to <code>b</code> 379 *@param len The amount of data to read 380 *@param timeout The timeout to use for reading 381 *@return The number of bytes actually read 382 *@throws IndyIOException If an IO error occurs. 383 *@throws PeerDisconnectedException if the remote machine has disconnected 384 *@throws ReadTimedOutException if the read opertaion timed out 385 *@throws NotConnectedException if the socket is not connected 386 *@throws IndexOutOfBoundsException if b,off, or len are illegal 387 *@throws NullPointerException if b is null 388 *@see read(byte[],int,int) 389 *@see read(byte[],int) 390 *@see read(byte[]) 391 *@see read() 392 */ 393 public int read(byte[] b, int off, int len, int timeout) 394 throws IndyIOException, ReadTimedOutException { 395 ensureOpen(); 396 397 if ((off | len | (off + len) | (b.length - (off + len))) < 0) { 398 throw new IndexOutOfBoundsException(); 399 } 400 else if (len == 0) { 401 return 0; 402 } 403 404 if (len == 0) { 405 return 0; 406 } 407 408 if (timeout < 0) { 409 timeout = 0; 410 } 411 412 try { 413 int oldTimeout = binding.getSoTimeout(); 414 415 binding.setSoTimeout(timeout); 416 417 try { 418 int nByte = input.read(b, off, len); 419 420 if (nByte == -1) { 421 close(); 422 throw new PeerDisconnectedException(IndyUtilities.getResourceString( 423 "RSConnectionClosedGracefully")); 424 } 425 426 return nByte; 427 } 428 catch (InterruptedIOException iioe) { 429 throw new ReadTimedOutException(IndyUtilities.getResourceString( 430 "RSReadTimedOut")); 431 } 432 finally { 433 if (binding != null) { 434 binding.setSoTimeout(oldTimeout); 435 } 436 } 437 } 438 catch (IOException ex) { 439 close(); 440 throw new IndyIOException(ex); 441 } 442 } 443 444 /*** 445 * Returns the number of bytes that be read from the socket and buffer without blocking 446 * 447 *@return The number of bytes that can be read without blocking 448 *@throws IndyIOException if an IO error occurs 449 */ 450 public int available() throws IndyIOException { 451 try { 452 return input.available(); 453 } 454 catch (IOException ex) { 455 throw new IndyIOException(ex); 456 } 457 } 458 459 /*** 460 * Connects to a remote socket using the parameters given in map. 461 * The map should take the following form: 462 * 463 * <table border="1" cellspacing="3"> 464 * <tr> 465 * <th>Key</th><th>Value</th><th>Type</th><th>Required</th> 466 * </tr> 467 * <tr> 468 * <td>"host"</td> 469 * <td>The IP address or FQDN of the remote host to connect to</td> 470 * <td>java.lang.String</td> 471 * <td>Yes</td> 472 * </tr> 473 * <tr> 474 * <td>"port"</td> 475 * <td>The port of the remote host to connect to</td> 476 * <td>java.lang.Stringr</td> 477 * <td>Yes</td> 478 * </tr> 479 * <tr> 480 * <td>"boundip"</td> 481 * <td>The local IP address to bind to</td> 482 * <td>java.lang.String</td> 483 * <td>No</td> 484 * </tr> 485 * <tr> 486 * <td>"boundport"</td> 487 * <td>The local port to bind to</td> 488 * <td>java.lang.String</td> 489 * <td>No</td> 490 * </tr> 491 * </table> 492 * 493 * Key names are case senstive (for now). Sorry. 494 * 495 * @param parameters The parameters to use for connection (see above) 496 * @param timeout The timeout to use for this connection attempt 497 * @throws IndyIOException if an IO error occurs. 498 * @throws IllegalArgumentException if <code>parameters</code> does not contain a required entry (see above) 499 */ 500 public void connectClient(Map parameters, int timeout) 501 throws IndyIOException { 502 if (parameters == null) { 503 throw new NullPointerException(); 504 } 505 506 String host = null; 507 String boundIP = null; 508 int port = 0; 509 int boundPort = 0; 510 511 host = (String) parameters.get("host"); 512 boundIP = (String) parameters.get("boundip"); 513 port = Integer.valueOf((String) parameters.get("port")).intValue(); 514 515 String boundPortStr = (String) parameters.get("boundport"); 516 517 if (boundPortStr != null) { 518 boundPort = Integer.valueOf(boundPortStr).intValue(); 519 } 520 521 connectClient(host, port, boundIP, boundPort, timeout); 522 } 523 524 /*** 525 * Connects this <code>IOHandlerSocket</code> to a remote socket whose address is given by 526 * <code>host</code> as either an IP address or FQDN and whose port is given by <code>port</code> 527 * 528 * If <code>boundIP</code> or <code>boundPort</code> are not <code>null</code> or < 1 respectively, the socket will bind 529 * to this local address and / or port. 530 * 531 * @param host The remote host to connect to. 532 * @param port The remote port to connect to. 533 * @param boundIP The local address to bind to 534 * @param boundPort The local port to bind to. 535 * @param timeout The timeout to use for this connection attempt 536 * @throws IndyIOException If an IO error occurs. 537 * @throws ConnectException If a connection error occurs, such as the connection being refused by the remote host 538 * @throws ConnectTimedOutException If the connection attempt times out 539 * @throws IndyUnknownHostException If the host can not be resolved. 540 */ 541 public void connectClient(String host, int port, String boundIP, 542 int boundPort, int timeout) 543 throws IndyIOException, ConnectException, 544 ConnectTimedOutException, IndyUnknownHostException { 545 //do some bounds checking here 546 if (host == null) { 547 throw new NullPointerException(IndyUtilities.getResourceString( 548 "RSNullHost")); 549 } 550 551 if ((port < 1) || (port > 0xFFFF)) { 552 throw new IllegalArgumentException(IndyUtilities.getResourceString( 553 "RSPortOutOfRange")); 554 } 555 556 if (IndyUtilities.isIP(host)) { 557 doStatus(Status.RESOLVING, new Object[] { host }); 558 } 559 560 try { 561 InetAddress local = InetAddress.getByName(boundIP); 562 InetAddress remote = InetAddress.getByName(host); 563 564 doStatus(Status.CONNECTING, null); 565 566 ConnectThread c = new ConnectThread(remote, port, local, boundPort); 567 568 c.start(); 569 570 try { 571 c.join(timeout); 572 } 573 catch (InterruptedException ie) { 574 //do nothing, but print a stack trace anyway 575 ie.printStackTrace(); 576 } 577 578 if (!c.getConnected()) { 579 //something nuked 580 throw new ConnectException(c.getException()); 581 } 582 else { 583 //we may have timed out 584 if (c.getSocket() == null) { 585 //try and interrupt the thread 586 c.interrupt(); 587 588 //raise error 589 throw new ConnectTimedOutException(IndyUtilities.getResourceString( 590 "RSConnectTimeout")); 591 } 592 else { 593 //we've connected! 594 binding = c.getSocket(); 595 596 try { 597 binding.setKeepAlive(false); 598 input = new MutableBufferedInputStream(binding.getInputStream()); 599 output = new BufferedOutputStream(binding.getOutputStream()); 600 601 if (readTimeOut > 0) { 602 setReadTimeOut(readTimeOut); 603 } 604 } 605 catch (IOException ex) { 606 ex.printStackTrace(); 607 binding = null; 608 throw new IndyIOException(ex); 609 } 610 611 connected = true; 612 doOnConnect(); 613 } 614 } 615 } 616 catch (UnknownHostException uhe) { 617 throw new IndyUnknownHostException(uhe); 618 } 619 } 620 621 /*** 622 * Closes this socket connection. 623 */ 624 public void close() { 625 if (binding != null) { 626 try { 627 binding.getOutputStream().flush(); 628 629 630 //binding.shutdownInput(); 631 //binding.shutdownOutput(); 632 doOnDisconnect(); 633 } 634 catch (IOException ioe) { 635 ioe.printStackTrace(); 636 } 637 finally { 638 try { 639 connected = false; 640 input.close(); 641 output.close(); 642 binding.close(); 643 } 644 catch (IOException ioe) { 645 ioe.printStackTrace(); 646 } 647 finally { 648 input = null; 649 output = null; 650 binding = null; 651 } 652 } 653 } 654 } 655 656 /*** 657 * Clears the internal buffer used by this socket 658 */ 659 public void clearBuffer() { 660 if (input != null) { 661 input.clear(); 662 } 663 } 664 665 /*** 666 * Reads a line of data from the socket and assembles it using the given encoding. 667 * If enoding is <code>null</code> the default platform encoding is used. 668 * 669 * @param timeout The timeout to use for this operation 670 * @param maxLineLength The maxiumum line length to accept 671 * @param encoding The character encoding to use to assmble the string 672 * @return A line of data from the socket 673 * @throws IndyIOException if an IO error occurs 674 * @throws PeerDisconnectedException if the remote machine disconnects normally 675 * @throws ReadTimedOutException if the operation times out 676 * @throws MaxLineLengthExceededException if the maximum line length is exceeded before a line break is found 677 * @see readLine(int,int) 678 */ 679 public String readLine(int timeout, int maxLineLength, String encoding) 680 throws IndyIOException, PeerDisconnectedException, 681 ReadTimedOutException, MaxLineLengthExceededException { 682 try { 683 ensureOpen(); 684 byteBuffer.reset(); 685 686 int oldTimeout = binding.getSoTimeout(); 687 688 try { 689 timeout_loop: 690 for (long start = System.currentTimeMillis(); timeout > 0;) { 691 binding.setSoTimeout(timeout); 692 693 int b = read(); 694 695 switch (b) { 696 //we have a CR - check to see if the next char is a LF 697 case CR: 698 input.mark(1); 699 700 if (input.available() > 0) { 701 int nextByte = input.read(); 702 703 if (nextByte != LF) { 704 input.reset(); 705 } 706 } 707 708 case LF: 709 710 // we have an LF (or a fall through from CR) , in which case return 711 return (encoding == null) 712 ? new String(byteBuffer.toByteArray()) 713 : new String(byteBuffer.toByteArray(), encoding); 714 715 default: 716 byteBuffer.write(b); 717 718 if (byteBuffer.size() > maxLineLength) { 719 throw new MaxLineLengthExceededException(IndyUtilities.getResourceString( 720 "RSMaxLineLengthExceeded")); 721 } 722 } 723 724 timeout -= (System.currentTimeMillis() - start); 725 } 726 727 throw new ReadTimedOutException(IndyUtilities.getResourceString( 728 "RSReadTimedOut")); 729 } 730 finally { 731 if (binding != null) { //we may have closed, so check 732 binding.setSoTimeout(oldTimeout); 733 } 734 } 735 } 736 catch (IOException ex) { 737 close(); 738 throw new IndyIOException(ex); 739 } 740 } 741 742 /*** 743 * Returns the current data that can be read from the socket without blocking 744 * 745 * @return The data avilable without blocking 746 * @throws IndyIOException If an IO error occurs. 747 * @NotConnectedException if the socket is not connected 748 */ 749 public byte[] currentReadBuffer() throws IndyIOException { 750 ensureOpen(); 751 752 return input.currentBuffer(); 753 } 754 755 private void ensureOpen() throws NotConnectedException { 756 if (binding == null) { 757 connected = false; 758 throw new NotConnectedException(IndyUtilities.getResourceString( 759 "RSNotConnected")); 760 } 761 } 762 763 private boolean testConnected() throws IOException { 764 int oldTimeout = binding.getSoTimeout(); 765 766 try { 767 /*** @todo Make this timeout a property? */ 768 binding.setSoTimeout(250); 769 input.mark(1); 770 771 try { 772 int b = input.read(); 773 774 if (b == -1) { 775 return false; 776 } 777 else { 778 input.reset(); 779 780 return true; 781 } 782 } 783 catch (InterruptedIOException iioe) { 784 //timed out, so still connected 785 return true; 786 } 787 } 788 finally { 789 binding.setSoTimeout(oldTimeout); 790 } 791 } 792 793 /*** 794 * DOCUMENT ME! 795 * 796 * @param newReadTimeOut DOCUMENT ME! 797 * 798 * @throws IndyIOException DOCUMENT ME! 799 */ 800 public void setReadTimeOut(int newReadTimeOut) throws IndyIOException { 801 super.setReadTimeOut(newReadTimeOut); 802 803 if (binding != null) { 804 try { 805 binding.setSoTimeout(newReadTimeOut); 806 } 807 catch (SocketException ex) { 808 throw new IndyIOException(ex); 809 } 810 } 811 } 812 813 /*** 814 * DOCUMENT ME! 815 * 816 * @return DOCUMENT ME! 817 * 818 * @throws IndyIOException DOCUMENT ME! 819 */ 820 public int getReadTimeOut() throws IndyIOException { 821 if (binding != null) { 822 try { 823 return binding.getSoTimeout(); 824 } 825 catch (SocketException ex) { 826 throw new IndyIOException(ex); 827 } 828 } 829 else { 830 return super.getReadTimeOut(); 831 } 832 } 833 834 private class MutableBufferedInputStream extends BufferedInputStream { 835 MutableBufferedInputStream(InputStream in) { 836 super(in); 837 } 838 839 public void clear() { 840 count = 0; 841 pos = 0; 842 } 843 844 public byte[] currentBuffer() throws IndyIOException { 845 try { 846 int avail = this.available(); 847 byte[] res = new byte[avail]; 848 849 if (avail == 0) { 850 if (!testConnected()) { 851 IOHandlerSocket.this.close(); 852 throw new PeerDisconnectedException(IndyUtilities.getResourceString( 853 "RSConnectionClosedGracefully")); 854 } 855 } 856 857 int b = this.read(res); 858 859 if (b == -1) { 860 throw new PeerDisconnectedException(IndyUtilities.getResourceString( 861 "RSConnectionClosedGracefully")); 862 } 863 864 return res; 865 } 866 catch (IOException ex) { 867 throw new IndyIOException(ex); 868 } 869 } 870 } 871 872 /*** 873 * Thread that performs blocking connect in background. 874 * 875 *@author owen 876 */ 877 private class ConnectThread extends Thread { 878 private InetAddress _host; 879 private int _port; 880 private InetAddress _boundIP; 881 private int _boundPort; 882 private IOException exception = null; 883 private Socket sock = null; 884 885 /*** 886 * Constructor for the ConnectThread object 887 * 888 *@param host Remote host. 889 *@param port Remote port. 890 *@param boundIP Local IP. 891 *@param boundPort Local port. 892 */ 893 public ConnectThread(InetAddress host, int port, InetAddress boundIP, 894 int boundPort) { 895 _host = host; 896 _port = port; 897 _boundIP = boundIP; 898 _boundPort = boundPort; 899 } 900 901 /*** 902 * Gets the exception attribute of the ConnectThread object 903 * 904 *@return The exception value 905 */ 906 public synchronized IOException getException() { 907 return exception; 908 } 909 910 /*** 911 * Gets the connected attribute of the ConnectThread object 912 * 913 *@return The connected value 914 */ 915 public synchronized boolean getConnected() { 916 return exception == null; 917 } 918 919 /*** 920 * Gets the socket attribute of the ConnectThread object 921 * 922 *@return The socket value 923 */ 924 public synchronized Socket getSocket() { 925 return sock; 926 } 927 928 /*** 929 * Main processing method for the ConnectThread object 930 */ 931 public void run() { 932 try { 933 Socket s = new Socket(this._host, this._port, this._boundIP, 934 this._boundPort); 935 936 if (useNagle) { 937 s.setTcpNoDelay(true); 938 } 939 else { 940 s.setTcpNoDelay(false); 941 } 942 943 sock = s; 944 } 945 catch (IOException ioe) { 946 exception = ioe; 947 } 948 } 949 } 950 }

This page was automatically generated by Maven